package executor

import (
	"fmt"
	"log"
	"mini-sql/config"
	"mini-sql/parser"
	"mini-sql/parsing"
	"mini-sql/planner"
	"mini-sql/planner/plan"
	"mini-sql/storage"
	"mini-sql/utils"
	"reflect"
	"runtime"

	"github.com/antlr4-go/antlr/v4"
)

type MyTreeNode struct {
	Depth      int           `json:"Depth"`
	Type       string        `json:"Type"`
	Text       string        `json:"Text"`
	ChildCount int           `json:"ChildCount"`
	Children   []*MyTreeNode `json:"Children,omitempty"`
}

type Executor struct {
	StorePool *storage.StorePool
}

func convertToMyNode(tree antlr.Tree, depth int) *MyTreeNode {
	if tree == nil {
		return nil
	}
	result := MyTreeNode{
		Type:       reflect.TypeOf(tree).String(),
		Text:       fmt.Sprintf("%v", tree),
		Depth:      depth,
		ChildCount: tree.GetChildCount(),
	}

	for _, child := range tree.GetChildren() {
		result.Children = append(result.Children, convertToMyNode(child, depth+1))
	}

	return &result
}

func formatTreeNode(tree antlr.Tree) any {
	node := convertToMyNode(tree, 0)
	return utils.FormatJSONPretty(node)
}

func NewExecutor() *Executor {
	return &Executor{}
}

func (e *Executor) ExecuteSQL(sql string) error {
	// antlr文档 https://github.com/antlr/antlr4/blob/master/doc/go-target.md
	defer func() {
		r := recover()
		if r != nil {
			buf := make([]byte, 1024)
			n := runtime.Stack(buf, false)
			stackInfo := string(buf[:n])
			log.Printf("recover from panic: %v", r)
			fmt.Printf("Stack trace:\n%v\n", stackInfo)
		}
	}()
	if config.DebugExecutor {
		log.Printf("RUNING SQL: %v", sql)
	}
	if e.StorePool == nil {
		panic("StorePool is nil")
	}
	inputStream := antlr.NewInputStream(sql)
	lexer := parser.NewSQLiteLexer(inputStream)
	tokenStream := antlr.NewCommonTokenStream(lexer, antlr.TokenDefaultChannel)
	// parserListener := parsing.NewEmptyParserListener()
	errListener := parsing.NewErrorListener()
	myParser := parser.NewSQLiteParser(tokenStream)
	myParser.AddErrorListener(errListener)
	// myParser.AddParseListener(parserListener)

	// 触发解析
	tree := myParser.Parse()
	ast := parsing.ConvertToAstTree(tree)

	if config.PrintAntlrTree {
		log.Printf("tree.type=%v", reflect.TypeOf(tree))
		log.Printf("tree.Format=%v", formatTreeNode(tree))
	}
	if config.PrintAstTree {
		log.Printf("tree.ast=%v", utils.FormatJSONPretty(ast))
	}

	for _, statement := range ast {
		plan := planner.CreatePlan(statement, e.StorePool)
		if plan != nil {
			err := plan.Prepare()
			if err != nil {
				return err
			}
			err = e.iterTuples(plan)
			if err != nil {
				return err
			}
		}
	}
	return nil
}

func (e *Executor) iterTuples(plan plan.PlanNode) error {
	for {
		tuple, err := plan.GetNextTuple()
		if err != nil {
			return err
		}
		if tuple == nil {
			break
		} else {
			// todo 支持外部消费者消费
			fmt.Println(tuple)
		}
	}
	return nil
}
